unit mControls;
{$i mPlatform.inc}
interface

uses
  Classes, SysUtils, mGraphics, mSets;
type
  TAlign = (alNone,alTop,alBottom,alLeft,alRight,alClient);
  { TControl }

  TControl = class(TComponent)
  private
    function GetControlCount: integer;
    function GetControls(i: integer): TControl;

  protected
    FParent: TComponent;
    FOnClick: TNotifyEvent;
    FOnResize: TNotifyEvent;
    FAutoSize:Boolean;
    FCaption: AnsiString;
    FColor: TColor;
    FAlign: TAlign;
    FHeight: integer;
    FLeft: integer;
    FTop: integer;
    FWidth: integer;
    FShownFirst:Boolean;
    procedure SetParent(AValue: TComponent);virtual;
    procedure SetHeight(AValue: integer);virtual;
    procedure Show;virtual;
    procedure SetLeft(AValue: integer);virtual;
    procedure SetTop(AValue: integer);virtual;
    procedure SetWidth(AValue: integer);virtual;
    procedure SetAlign(AValue: TAlign);virtual;
    procedure SetColor(AValue: TColor);virtual;
    procedure SetCaption(AValue: AnsiString);virtual;
    procedure wmLButtonUp(var MSG:mSets.TMessage);message wm_LButtonUp;

    function GetText: AnsiString;virtual;
    procedure SetText(AValue: AnsiString);virtual;
    procedure SetAutoSize(AValue: Boolean);virtual;
    property AutoSize:Boolean read FAutoSize write SetAutoSize default false;
    property Caption:AnsiString read FCaption write SetCaption;
    property Text:AnsiString read GetText write SetText;
    property Color:TColor read FColor write SetColor;
    //events
    property OnResize:TNotifyEvent read FOnResize write FOnResize;
    property OnClick:TNotifyEvent read FOnClick write FOnClick;
  public
    property Align:TAlign read FAlign write SetAlign;
    constructor Create(AOwner: TComponent); override;
    procedure ProcessEvent(Ev:pointer);virtual;
    property Parent:TComponent read FParent write SetParent;
    procedure Repaint;virtual;
    property Controls[i:integer]:TControl read GetControls;
    property ControlCount:integer read GetControlCount;
  published
    property Name;
    property Width:integer read FWidth write SetWidth;
    property Height:integer read FHeight write SetHeight;
    property Left:integer read FLeft write SetLeft;
    property Top:integer read FTop write SetTop;
  end;

  { TWinControl }

  TWinControl = class(TControl)
  private
  protected
    FOnPaint: TNotifyEvent;
    FCtrlExtData: AnsiString;
    FHandle:THandle;
    FCanvas: TCanvas;
    FWinCreated:boolean;
    FSpecificHandling:Boolean;//Set true if window presents, but handles in decendent
    function GetRealWindow: boolean;virtual;
    procedure wmPaint(var MSG:TMessage);message wm_paint;
    procedure SetLeft(AValue: integer); override;
    procedure SetTop(AValue: integer); override;
    procedure SetWidth(AValue: integer); override;
    procedure SetHeight(AValue: integer); override;
    procedure SetParent(AValue: TComponent); override;
    //Events
    property Canvas:TCanvas read FCanvas;
  public
    property RealWindow:boolean read GetRealWindow;
    property Handle:THandle read FHandle;
    procedure Show; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property OnPaint:TNotifyEvent read FOnPaint write FOnPaint;
  end;


  { TCustomButton }

  TCustomButton = class(TWinControl)
  private
    FPressed: Boolean;
  protected
    procedure wmPaint(var Msg:mSets.TMessage);message wm_Paint;
    procedure wmLButtonDown(var Msg:mSets.TMessage);message wm_LButtonDown;
    procedure wmLButtonUp(var MSG: mSets.TMessage); message wm_LButtonUp;
  public
    property Caption;
    property OnClick;
    property Color;
    function GetRealWindow: boolean; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Pressed:Boolean read FPressed;
    procedure SetCaption(AValue: AnsiString); override;
  end;

  TButton = class(TCustomButton)
  published
    property Caption;
    property OnClick;
    property Color;
    property OnPaint;
  end;
  TCustomEdit = class(TWinControl)
  public
    property Text;
  end;

//OK, it is Win-specific function, but it is easier to leave it in all platforms
{&stdcall+}
function AllWndProc(H:DWord;msg:DWord;wprm:LongInt;lprm:LongInt):longint;{$ifndef virtualpascal}stdcall;{$endif}
{&stdcall-}

implementation
{$i mctrlwin.inc}
{$i mctrlunx.inc} //better for lazarus, worse for compiler
{ TCustomButton }

procedure TCustomButton.wmPaint(var Msg: mSets.TMessage);
begin
  //TODO: win native
  if FHandle=0 then exit;
  if Canvas.Handle=0 then Canvas.ActualizeWin(FHandle);
  if not Skin(self) then
  begin
    Canvas.Color:=clBlack;//todo
    Canvas.Rectangle(0,0,Width,Height);
    if not FPressed then Canvas.Color:=clWhite else Canvas.Color:=clBlack;
    Canvas.MoveTo(1,1);
    Canvas.LineTo(1,Width-1);
    Canvas.MoveTo(1,1);
    Canvas.LineTo(Height-1,1);
    if FPressed then Canvas.Color:=clWhite else Canvas.Color:=clBlack;
    Canvas.MoveTo(1,Width-1);
    Canvas.LineTo(Height-1,Width-1);
    Canvas.LineTo(Height-1,1);
    Canvas.Color:=FColor;
    Canvas.FilledRectangle(2,2,Width-2,Height-2);
    Canvas.Color:=not Canvas.Color;
    if (Canvas.Color-FColor)<$20 then Canvas.Color:=clBlack;
    Canvas.TextOut(4,Height div 2-5,FCaption);//TODO: Exact position!
  end;
  inherited wmPaint(MSG);
end;

procedure TCustomButton.wmLButtonDown(var Msg: mSets.TMessage);
begin
  FPressed:=true;
  Msg.Result:=0;
  Repaint;
end;

procedure TCustomButton.wmLButtonUp(var MSG: mSets.TMessage);
begin
  inherited wmLButtonUp(Msg);
  FPressed:=false;
  Repaint ;
end;

function TCustomButton.GetRealWindow: boolean;
begin
  Result:=true;
end;

constructor TCustomButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

destructor TCustomButton.Destroy;
begin
  inherited Destroy;
end;

procedure TCustomButton.SetCaption(AValue: AnsiString);
begin
  if FCaption=AValue then exit;
  FCaption:=AValue;
  Repaint;
end;

procedure TWinControl.wmPaint(var MSG: mSets.TMessage);
begin
  if Assigned(FOnPaint) then OnPaint(self);
end;

constructor TWinControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCanvas:=TCanvas.Create;//No real creation
  FWinCreated:=false;
  FSpecificHandling:=false;
end;


{ TControl }

function TControl.GetText: AnsiString;
begin
  Result:=FCaption;
end;

procedure TControl.SetText(AValue: AnsiString);
begin
  SetCaption(AValue);
end;

function TControl.GetControlCount: integer;
var
  i: Integer;
begin
  Result:=0;
  for i:=0 to ComponentCount-1 do
    if Components[i]<>nil then if Components[i] is TControl then inc(Result);
end;

function TControl.GetControls(i: integer): TControl;
var
  j: Integer;
  k: Integer;
begin
  k:=-1;
  for j:=0 to ComponentCount-1 do
  begin
    if Components[j]<>nil then if Components[j] is TControl then inc(k);
    if k=i then begin Result:=Components[j] as TControl;exit;end;
  end;
  Result:=nil;
end;

procedure TControl.SetParent(AValue: TComponent);
begin
  if FParent=AValue then Exit;
  FParent:=AValue;
end;

procedure TControl.SetHeight(AValue: integer);
begin
  if FHeight=AValue then Exit;
  FHeight:=AValue;
end;

procedure TControl.Show;
begin

end;

procedure TControl.SetLeft(AValue: integer);
begin
  if FLeft=AValue then Exit;
  FLeft:=AValue;
end;

procedure TControl.SetTop(AValue: integer);
begin
  if FTop=AValue then Exit;
  FTop:=AValue;
end;

procedure TControl.SetWidth(AValue: integer);
begin
  if FWidth=AValue then Exit;
  FWidth:=AValue;
end;

procedure TControl.SetAlign(AValue: TAlign);
begin
  if FAlign=AValue then Exit;
  FAlign:=AValue;
end;

procedure TControl.SetColor(AValue: TColor);
begin
  if FColor=AValue then Exit;
  FColor:=AValue;
end;

procedure TControl.SetCaption(AValue: AnsiString);
begin
  if FCaption=AValue then Exit;
  FCaption:=AValue;
end;


procedure TControl.wmLButtonUp(var MSG: mSets.TMessage);
begin
  if Assigned(OnClick) then OnClick(self);
end;


procedure TControl.Repaint;
var MSG:TMessage;
begin
  MSG.MSG:=wm_paint;
  MSG.Result:=1;
  Dispatch(Msg);
end;

procedure TControl.SetAutoSize(AValue: Boolean);
begin
  if FAutoSize=AValue then Exit;
  FAutoSize:=AValue;
end;

constructor TControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FShownFirst:=false;;
end;

initialization
  InitMctrl;
finalization
end.
